package cn.chen.sparkproject.jdbc;

import cn.chen.sparkproject.conf.ConfigurationManager;
import cn.chen.sparkproject.constant.Constants;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;

public class JdbcHelper {

    static {
        try {
            String driver = ConfigurationManager.getProperty(Constants.JDBC_DRIVER);
            Class.forName(driver);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public LinkedList<Connection> datasource = new LinkedList<Connection>();

    private JdbcHelper(){
        int datasourceSize = ConfigurationManager.getInteger(Constants.JDBC_DATASOURCE_SIZE);
        for(int i = 0;i < datasourceSize;i ++){
            String url = ConfigurationManager.getProperty(Constants.JDBC_URL);
            String user = ConfigurationManager.getProperty(Constants.JDBC_USER);
            String password = ConfigurationManager.getProperty(Constants.JDBC_PASSWORD);
            try {
                Connection conn = DriverManager.getConnection(url, user, password);
                datasource.push(conn);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }

   public synchronized Connection getConnection(){
        while(datasource.size() == 0){
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return datasource.poll();
   }

   public int executeUpdate(String sql, Object[] params){
       int result = 0;
       Connection conn = null;
       PreparedStatement pstmt = null;

       try{
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);

            for(int i = 0; i < params.length;i ++){
                pstmt.setObject(i + 1, params[i]);
            }

            result = pstmt.executeUpdate();

       }catch (Exception e){
            e.printStackTrace();
       }finally {
           if(conn != null){
               datasource.push(conn);
           }
       }
       return result;
   }

   public void executeQuery(String sql, Object[] params, QueryCallback callback){
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        try {
            conn = getConnection();
            pstmt = conn.prepareStatement(sql);

            for(int i = 0;i < params.length;i ++){
                pstmt.setObject(i + 1, params[i]);
            }

            rs = pstmt.executeQuery();
            callback.process(rs);
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if(conn != null){
                datasource.push(conn);
            }
        }
   }

    /**
     * 批量执行sql语句
     * @param sql
     * @param paramsList
     * @return 每条sql语句影响的行数
     */
   public int[] executeBatch(String sql, List<Object[]> paramsList){
        int[] rtn = null;
        Connection conn = null;
        PreparedStatement pstmt = null;

        try {
            conn = getConnection();
            // 1.取消启动提交
            conn.setAutoCommit(false);
            pstmt = conn.prepareStatement(sql);

            // 2.批量加入参数
            for(Object[] params : paramsList){
                for(int i = 0;i < params.length;i ++){
                    pstmt.setObject(i + 1, params[i]);
                }
                pstmt.addBatch();
            }
            // 3.执行批量sql
            rtn = pstmt.executeBatch();

            // 4.提交
            conn.commit();
        }catch (Exception e){
            e.printStackTrace();
        }

        return rtn;
   }

   public static interface QueryCallback{
       /**
        * 处理查询结果
        * @param rs
        * @throws Exception
        */
       void process(ResultSet rs) throws Exception;
   }

    private static class JdbcHelperWrapper{
        static JdbcHelper instance = new JdbcHelper();
    }

    public static JdbcHelper getInstance(){
        return JdbcHelperWrapper.instance;
    }
}
